package org.wzl.databasesync.service.impl;

import jakarta.annotation.Resource;
import lombok.Data;
import lombok.ToString;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.wzl.databasesync.dto.DatabaseInfo;
import org.wzl.databasesync.dto.FiledDesc;
import org.wzl.databasesync.dto.SyncSqlDTO;
import org.wzl.databasesync.dto.SyncSqlResp;
import org.wzl.databasesync.dto.SyncTables;
import org.wzl.databasesync.dto.TableDesc;
import org.wzl.databasesync.service.DatabaseSyncService;
import org.wzl.databasesync.service.SqlGenService;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Slf4j
@Service
public class DatabaseSyncServiceImpl implements DatabaseSyncService {

    @Resource
    private SqlGenService sqlGenService;

    @Data
    @ToString
    public static
    class UpdateTable {
        private String tableName;
        private List<FiledDesc> addColumns;
        private List<FiledDesc> deleteColumns;
    }



    @Override
    public SyncSqlResp syncSql(SyncSqlDTO syncSqlDTO) throws Exception {
        log.info("syncSql: {}", syncSqlDTO);
        SyncTables syncTables = getSyncTables(syncSqlDTO);
        List<String> sql = getSyncSql(syncTables);
        return new SyncSqlResp(syncTables, sql);
    }

    private List<String> getSyncSql(SyncTables syncTables) {
        List<String> sql = new ArrayList<>();
        //新增表
        for (TableDesc addTable : syncTables.getAddTables()) {
            String createTableSql = sqlGenService.createTableSql(addTable);
            sql.add(createTableSql);
        }
        //删除表
        for (TableDesc deleteTable : syncTables.getDeleteTables()) {
            String dropTableSql = sqlGenService.dropTableSql(deleteTable);
            sql.add(dropTableSql);
        }
        //更新表
        for (UpdateTable updateTable : syncTables.getUpdateTables()) {
            String alterTableSql = sqlGenService.alterTableSql(updateTable);
            sql.add(alterTableSql);
        }
        return sql;
    }

    private SyncTables getSyncTables(SyncSqlDTO syncSqlDTO) throws Exception {
        //源数据库
        DatabaseInfo sourceDatabaseInfo = syncSqlDTO.getSourceDatabaseInfo();
        //目标数据库
        DatabaseInfo targetDatabaseInfo = syncSqlDTO.getTargetDatabaseInfo();

        List<TableDesc> addTables = new ArrayList<>();
        List<TableDesc> deleteTables = new ArrayList<>();
        List<UpdateTable> updateTables = new ArrayList<>();

        List<TableDesc> sourceTables = sqlGenService.getAllTables(sourceDatabaseInfo);
        List<TableDesc> targetTables = sqlGenService.getAllTables(targetDatabaseInfo);
        //计算出需要新增的表和删除的表
        if (sourceTables.size() != targetTables.size()) {
            for (TableDesc sourceTable : sourceTables) {
                if (!targetTables.contains(sourceTable)) {
                    addTables.add(sourceTable);
                }
            }
            for (TableDesc targetTable : targetTables) {
                if (!sourceTables.contains(targetTable)) {
                    deleteTables.add(targetTable);
                }
            }
        }

        Map<String, TableDesc> collect = targetTables.stream()
                .collect(Collectors.toMap(TableDesc::getTableName, tableDesc -> tableDesc));
        for (TableDesc sourceTable : sourceTables) {
            if (!collect.containsKey(sourceTable.getTableName())) {
                continue;
            }
            TableDesc targetTable = collect.get(sourceTable.getTableName());
            //计算需要新增的字段
            List<FiledDesc> addColumns = new ArrayList<>();
            for (FiledDesc sourceFiled : sourceTable.getFiledDescList()) {
                boolean flag = false;
                for (FiledDesc targetFiled : targetTable.getFiledDescList()) {
                    if (targetFiled.getField().equals(sourceFiled.getField())) {
                        flag = true;
                        break;
                    }
                }
                if (!flag) {
                    addColumns.add(sourceFiled);
                }
            }
            //计算需要删除的字段
            List<FiledDesc> deleteColumns = new ArrayList<>();
            for (FiledDesc targetFiled : targetTable.getFiledDescList()) {
                boolean flag = false;
                for (FiledDesc sourceFiled : sourceTable.getFiledDescList()) {
                    if (targetFiled.getField().equals(sourceFiled.getField())) {
                        flag = true;
                        break;
                    }
                }
                if (!flag) {
                    deleteColumns.add(targetFiled);
                }
            }

            UpdateTable updateTable = new UpdateTable();
            updateTable.setTableName(sourceTable.getTableName());
            updateTable.setAddColumns(addColumns);
            updateTable.setDeleteColumns(deleteColumns);
            updateTables.add(updateTable);
        }

        log.info("需要删除的表:{},需要新增的表:{},需要更新的表:{}", deleteTables, addTables, updateTables);

        return new SyncTables(addTables, deleteTables, updateTables);
    }

}
